/*
 * Copyright 2020 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

import { customer, order as orderApi, security, store } from "@mall/api-services"
import * as _ from "lodash"
import * as React from "react"
import { RouteComponentProps, withRouter } from "react-router"
import Button from "../components/button"
import Flex from "../components/flex"
import NavBar from "../components/navbar"
import ProductPrice from "../components/product/product-price"
import Icon from "../icon"
import session, { FILL_ORDERS_NAME, MAIN_SHIPPING_ADDRESS_NAME } from "../session"
import "./fill-order.scss"
import OrderItem from "./order-item"

interface OrderInfoProps {
  order: orderApi.Order;
}

interface OrderInfoState {
  storeInfo: store.Store;
}

class OrderInfo extends React.Component<OrderInfoProps, OrderInfoState> {

  public constructor(props: Readonly<OrderInfoProps>) {
    super(props)
    this.state = {
      storeInfo: new store.Store(),
    }
  }

  public componentDidMount(): void {
    this.refreshStoreInfo()
  }

  public render() {
    const { order } = this.props
    const { storeInfo } = this.state
    return (
      <div className="order-info">
        <div className="store-name">{storeInfo.name}</div>
        {_.map(order.items, item => <OrderItem key={item.variantId} item={item}/>)}
      </div>
    )
  }

  private refreshStoreInfo() {
    const { order } = this.props
    store.StoreServiceV1.getStore(order.storeId)
      .then(storeInfo => this.setState({ storeInfo }))
  }
}

interface FillOrderProps extends RouteComponentProps {

}

interface FillOrderState {
  shippingAddress: orderApi.ShippingAddress;
  orders: orderApi.Order[];
}

class FillOrder extends React.Component<FillOrderProps, FillOrderState> {

  public constructor(props: Readonly<FillOrderProps>) {
    super(props)

    this.state = {
      shippingAddress: new orderApi.ShippingAddress(),
      orders: [],
    }
    this.handleSubmitOrder = this.handleSubmitOrder.bind(this)
  }

  public componentDidMount(): void {
    this.setShippingAddress()
    this.setOrders()
  }

  public render() {
    const { history } = this.props
    const { shippingAddress, orders } = this.state
    const customerId = security.SecurityUserHolder.getUserId()
    return (
      <div className="fill-order">
        <NavBar left={<Icon onClick={() => history.goBack()}
                            type="left"/>}>填写订单</NavBar>
        <div className="order-content">
          <div className="shipping-address"
               onClick={() => history.push({
                 pathname: `/customers/${customerId}/delivery-addresses`,
                 search: "change-main-address",
               })}>
            <div className="shipping-address-lines">
              <div className="location">{shippingAddress.location}</div>
              <span className="address">{shippingAddress.address}</span>
              <div>{shippingAddress.lastName} {shippingAddress.firstName} {shippingAddress.mobile}</div>
            </div>
            <Icon type="right" size="xxs"/>
          </div>
          <div className="order-list">
            {_.map(orders, (order, index) => {
              return <OrderInfo key={index} order={order}/>
            })}
          </div>
          <div className="order-amounts">
            <Flex justifyContent="space-between" className="order-amount">
              <div>商品金额</div>
              <div><ProductPrice price={this.computeAmount()} size={13}/></div>
            </Flex>
            <Flex justifyContent="space-between" className="order-amount">
              <div>运费</div>
              <div><ProductPrice price={0} size={13}/></div>
            </Flex>
            <Flex justifyContent="space-between" className="order-amount">
              <div>退款无忧</div>
              <div><ProductPrice price={0} size={13}/></div>
            </Flex>
            <Flex justifyContent="space-between" className="order-amount">
              <div>立减</div>
              <div><ProductPrice price={0} size={13}/></div>
            </Flex>
          </div>
        </div>
        <Flex className="order-footer" alignItems="center" justifyContent="space-between">
          <ProductPrice price={this.computeAmount()} size={24}/>
          <Button type="primary" shape="circle" className="submit-order-button"
                  onClick={this.handleSubmitOrder}>提交订单</Button>
        </Flex>
      </div>
    )
  }

  private setShippingAddress() {
    const customerId = security.SecurityUserHolder.getUserId()
    const addressObject = session.get(MAIN_SHIPPING_ADDRESS_NAME)
    if (addressObject) {
      this.setState({
        shippingAddress: _.assign(new orderApi.ShippingAddress(), addressObject),
      })
    } else {
      customer.CustomerAddressServiceV1
        .getDefaultAddress(customerId)
        .then(address => {
          this.setState({
            shippingAddress: _.assign(new orderApi.ShippingAddress(), address),
          })
        })
    }
  }

  private setOrders() {
    const ordersObject = session.get(FILL_ORDERS_NAME)
    const orders = _.map(ordersObject, orderObject => {
      const order = _.assign(new orderApi.Order(), orderObject)
      order.items = _.map(orderObject.items, item => _.assign(new orderApi.OrderItem(), item, { id: undefined }))
      return order
    })

    this.setState({ orders })
  }

  private computeAmount() {
    const { orders } = this.state
    return _.chain(orders)
      .map(order => order.totalAmount)
      .sum()
      .value()
  }

  private handleSubmitOrder() {
    const { history } = this.props
    const { orders, shippingAddress } = this.state
    _.forEach(orders, order => {
      order.shippingAddress = shippingAddress
    })

    orderApi.OrderServiceV1.createOrders(orders)
      .then(savedOrders => {
        const orderIds = _.map(savedOrders).map(order => order.id)
        const totalAmount = _.reduce(savedOrders, (sumAmount, order) => sumAmount + order.totalAmount, 0)
        history.push({
          pathname: `/orders/payments`,
          search: `orders=${_.join(orderIds, ",")}&amount=${totalAmount}`,
        })
      })
  }
}

export default withRouter(FillOrder)
